package com.wholeintech.protocol;

import android.util.Log;

public class KNXBase {
	private static final String TAG="KNXBase";
    private static final int FRAME_HEAD = 0;
    private static final int SRC_ADDR_H = 1;
    private static final int SRC_ADDR_L = 2;
    private static final int DES_ADDR_H = 3;
    private static final int DES_ADDR_L = 4;
    private static final int OTHER= 5;
    private static final int OTHER2= 6;
    private static final int CTRL_DATA = 7;
    private static final int CHECKSUM = 8;
    
    private static final byte B10111100= (byte)0xBC;
    private static final byte B11100001= (byte)0xE1;
    private static final byte B10000000= (byte)0x80;
    private static final byte B11000000= (byte)0xC0;
    private static final byte B11111100= (byte)0xFB;
    private static final byte B00111111= (byte)0x3F;
    private static final byte B11110000= (byte)0xF0;
    
    private static final int MAX_FRAME_LENGTH =128;
    private static final int HANDER_FARME_LENGTH =6;
    
    private static final int B0000 =0x00;
    private static final int B0010 =0x02;
    
    private static final int KNX_COMMAND_WRITE = B0010;
    private static final int KNX_COMMAND_READ  = B0000;
    	
	private static byte[] KNX_CTRL_FMT = {(byte)0xBC,(byte)0xFF, (byte)0xFF, (byte)0x00, (byte)0x01, (byte)0xE1, 0x00, (byte)0x81, (byte)0x23};

	byte[]  mKnxFrameBuffer= new byte[MAX_FRAME_LENGTH];
	int mFrameLength;
		 
    public KNXBase() { 
    }
	 
	public byte[] getCtrlPacket(int mainGroup, int middleGroup, int subGroup, int data ){
		
		KNX_CTRL_FMT[DES_ADDR_H]=(byte)( (mainGroup&0xff)<<4 | ((middleGroup&0xff)) );
		KNX_CTRL_FMT[DES_ADDR_L]=(byte)(subGroup&0xff);
		
		KNX_CTRL_FMT[CTRL_DATA]=(byte)((data&0xff) | (byte)0x80);
		
		KNX_CTRL_FMT[CHECKSUM]=setChecksum(KNX_CTRL_FMT ,KNX_CTRL_FMT.length-1);
					
		return KNX_CTRL_FMT;
	}
	
	public byte[] getPacket(int area, int line , int addr , int cmd, byte[] data){
							
		return KNX_CTRL_FMT;
	}
	
	byte setChecksum(byte[] data ,int len) {
		  int bcc = 0x00;
		  int i;
		  for(i=0;i<len;i++) {
		    bcc ^= data[i];
		  }
		  return ((byte)(~bcc));
	}
	
	byte setChecksum() {
		  int bcc = 0x00;
		  int i;
		  for(i=0;i<mFrameLength;i++) {
		    bcc ^= mKnxFrameBuffer[i];
		  }		  
		  mFrameLength++;	
		  mKnxFrameBuffer[mFrameLength-1]=(byte)(~bcc);
		  
		  return ((byte)(~bcc));
	}
	
	private void clean()
	{
	  int i;
	  for(i=0;i<MAX_FRAME_LENGTH;i++) {
	    mKnxFrameBuffer[i] = 0;
	  }
	  //Control feild
	  mKnxFrameBuffer[0]= B10111100;
	  // Target group address, Router counter =6, length =1 (= 2 data bytes)
	  mKnxFrameBuffer[5]= B11100001;

	}

	private void initKnxFrame(int fd) {		
	  //knxFrame = (struct KnxFrameType*)malloc(sizeof(struct KnxFrameType));
	  //knxRecFrame = (struct KnxFrameType*)malloc(sizeof(struct KnxFrameType)); //new: init  KnxRecFrame
	  //knxFrame->fd=fd;
	}

	private void setSourceAddress(int area, int line, int mumber) {
	  mKnxFrameBuffer[1] =(byte)((area << 4) | line);
	  mKnxFrameBuffer[2] =(byte) mumber;
	}

	private void setTargetGroupAddress(int main, int middle, int sub) {
	    mKnxFrameBuffer[3] = (byte)((main << 3) | middle);
	    mKnxFrameBuffer[4] = (byte)sub;
	    mKnxFrameBuffer[5]|= B10000000;
	}

	private void setFirsetDataByte(int data) {
	  mKnxFrameBuffer[7] &= B11000000;
	  mKnxFrameBuffer[7] |= data;
	}

	private void setSecondDataByte(byte data)
	{
		mKnxFrameBuffer[7] &= B11000000;
		mKnxFrameBuffer[8] = data;
		
	}

	private void setCommand(byte command) {
	  mKnxFrameBuffer[6] &= B11111100;
	  mKnxFrameBuffer[7] &= B00111111;

	  mKnxFrameBuffer[6] |= (byte)(command >>2);
	  mKnxFrameBuffer[7] |= (byte)(command <<6);
	}

	private void setPayloadLength(int payloadlength) {
	  mKnxFrameBuffer[5] &= B11110000;
	  mKnxFrameBuffer[5] |= (payloadlength -1);

	 mFrameLength = payloadlength + HANDER_FARME_LENGTH;
	}
	
	void createKNXMessageFrame(int payloadlength, byte command, int mainGroup, int middleGroup, int subGroup, int firstDataByte) {
		  clean();
		  setSourceAddress((int)0xff,(int)0xff,(int)0xff);
		  setTargetGroupAddress(mainGroup,middleGroup,subGroup);
		  setFirsetDataByte(firstDataByte);
		  setCommand(command);
		  setPayloadLength(payloadlength);
		  setChecksum();
	}

	byte[] getBytesFrame(int fd) {
		byte[] out=new byte[mFrameLength];		
		System.arraycopy(mKnxFrameBuffer, 0, out, 0, mFrameLength);		
		return out;
	}

	byte[]  groupWriteBool(int fd,int mainGroup, int middleGroup, int subGroup, int value) {
	  byte valueBool = 0;
	  int i=0;
	  /*if(value!=0) {
	    valueBool =0x01;
	  }*/
	  valueBool =(byte)(value&0x00ff);
	  
	  initKnxFrame(fd);

	  createKNXMessageFrame(2,(byte)KNX_COMMAND_WRITE,mainGroup,middleGroup,subGroup,valueBool);

	  return getBytesFrame(fd);
	}

	byte[] groupWriteByte(int fd,int mainGroup, int middleGroup, int subGroup, int value)
	{
		int i=0;
		byte valueByte = (byte)(value&0xFF);

		initKnxFrame(fd);
		clean();

	  	//setSourceAddress(1,1,2);
		setSourceAddress((int)0xff,(int)0xff,(int)0xff);
	  	setTargetGroupAddress(mainGroup,middleGroup,subGroup);
	  	setSecondDataByte(valueByte);
	  	setCommand((byte)KNX_COMMAND_WRITE);
	  	setPayloadLength(3);
	  	setChecksum();	
		/***
		for(i=0;i<knxFrame->frameLength;i++) {
	  		printf("%0x\n", knxFrame->knxFrameBuffer[i]);
		}**/
		return getBytesFrame(fd);    
		//createKNXMessageFrame(3,KNX_COMMAND_WRITE,mainGroup,middleGroup,subGroup,valueByte);
	}
	
	byte[] groupWriteFloat(int fd,int mainGroup, int middleGroup, int subGroup, float value)
	{
		int i=0;
		byte valueByte1 = 0;
		byte valueByte2 = 0;
		int temp;
		int evalue=15;
		if(value<0){
			valueByte1=(byte)0x80;
			value=-value;
		}
		
		value=value*100;
		temp=(int)value;
		
		for (i=0; i<16; i++)
		{
			temp=temp>>i;
			if(temp<2048)
			{
				evalue=i;
				break;
			}
		}
			
		valueByte1 |=(((byte)evalue<<3)&0x78);
		
		Log.e(TAG, "evalue:"+evalue + " temp2:" +temp);
		
		valueByte1 |=((temp>>8)&0x07);
		valueByte2 |=(byte)(temp);
				
		initKnxFrame(fd);
		clean();

	  	setSourceAddress((int)0xff,(int)0xff,(int)0xff);
	  	setTargetGroupAddress(mainGroup,middleGroup,subGroup);
	  	setCommand((byte)KNX_COMMAND_WRITE);
	  	setSecondDataByte(valueByte1);
	  	mKnxFrameBuffer[9]=valueByte2;
	  	setPayloadLength(4);
	  	setChecksum();	
		/***
		for(i=0;i<knxFrame->frameLength;i++) {
	  		printf("%0x\n", knxFrame->knxFrameBuffer[i]);
		}**/
		return getBytesFrame(fd);    
		//createKNXMessageFrame(3,KNX_COMMAND_WRITE,mainGroup,middleGroup,subGroup,valueByte);
	}

	byte[]  groupReadBoolReq(int fd, int mainGroup, int middleGroup, int subGroup, int value)
	{
		int valueBool=0;
		int i;

		initKnxFrame(fd);

		createKNXMessageFrame(2,(byte)KNX_COMMAND_READ,mainGroup,middleGroup,subGroup,valueBool);
		/***
		for(i=0;i<knxFrame->frameLength;i++) {
			printf("%02x\n", knxFrame->knxFrameBuffer[i]);
		
	    }**/

		return getBytesFrame(fd);
	}

	byte[]  groupReadByte(int fd, int mainGroup, int middleGroup, int subGroup)
	{
		initKnxFrame(fd);
		clean();
	  	//setSourceAddress(1,1,2);
		setSourceAddress((int)0xff,(int)0xff,(int)0xff);
	  	setTargetGroupAddress(mainGroup,middleGroup,subGroup);
	  	setFirsetDataByte(0);
	  	setCommand((byte)KNX_COMMAND_READ);
	  	setPayloadLength(2);
	  	setChecksum();		
		return getBytesFrame(fd);
	}	
}
